﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MoneyWentWhere.SimpleTextFile.ExchangeRates
{
    /// <summary>
    /// Exchange rates based on transfers between different-currency 
    /// accounts within a MWW data file.
    /// </summary>
    public class LocalExchangeRateSource : IExchangeRateSource
    {
        readonly MwwDataFile Data;

        public LocalExchangeRateSource(MwwDataFile dataFile)
        {
            if (dataFile == null) { throw new ArgumentNullException("dataFile"); }

            Data = dataFile;
        }

        public IEnumerable<ExchangeRate> GetExchangeRates()
        {
            var transfers = Data.Accounts
                .SelectMany(x => x.Transactions.Where(tx => tx is Transfer)).Cast<Transfer>();

            Dictionary<String, Transfer> transfersById = transfers.ToDictionary(x => x.Id);

            var rates = transfers.Select(tFrom => GetExchangeRate(tFrom, transfersById)).Where(x => x != null);

            return rates;
        }

        static ExchangeRate GetExchangeRate(Transfer from, Dictionary<String, Transfer> transfersById)
        {
            if (from == null) { throw new ArgumentNullException("from"); }
            
            Transfer to;
            if (transfersById.TryGetValue(from.TargetId, out to) == false) { return null; }
            return GetExchangeRate(from, to);
        }

        public static ExchangeRate GetExchangeRate(Transfer from, Transfer to)
        {
            if (from == null) { throw new ArgumentNullException("from"); }
            if (to == null) { throw new ArgumentNullException("to"); }

            if (from.Account.Currency == null) { return null; }
            if (to.Account.Currency == null) { return null; }
            if (from.Account.Currency == to.Account.Currency) { return null; }
            if (from.Amount == 0 || to.Amount == 0) { return null; }

            return new ExchangeRate(
                from.Date,
                from.Account.Currency,
                to.Account.Currency,
                Math.Abs(to.Amount / from.Amount),
                String.Format("Transfer {0} to {1}", from.Id, to.Id));
        }

    }
}
